package gov.pbc.nn.kjgl.fxq.organDocument.view;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.exception.NoneLoginException;
import com.bstek.bdf2.core.orm.hibernate.ISessionCallback;
import com.bstek.dorado.annotation.DataProvider;
import com.bstek.dorado.annotation.DataResolver;
import com.bstek.dorado.annotation.Expose;
import com.bstek.dorado.data.entity.EntityState;
import com.bstek.dorado.data.entity.EntityUtils;
import com.bstek.dorado.data.provider.Criteria;
import com.bstek.dorado.data.provider.Page;
import com.bstek.dorado.data.variant.Record;

import gov.pbc.nn.core.bdf.entity.Dept;
import gov.pbc.nn.core.dao.CommonHibernateDao;
import gov.pbc.nn.core.dao.PbcnnCoreJdbcDao;
import gov.pbc.nn.kjgl.fxq.attachment.AttachmentEntity;
import gov.pbc.nn.kjgl.fxq.organDocument.entity.OrganDocumentEntity;
import gov.pbc.nn.kjgl.fxq.organInfor.entity.OrganInfor;
import gov.pbc.nn.kjgl.fxq.workDocument.view.WorkDocumentPR;

@Component(OrganDocumentPR.BEAN_ID)
public class OrganDocumentPR extends CommonHibernateDao {
	public static final String BEAN_ID = "organDocumentPR";

	@Resource(name = PbcnnCoreJdbcDao.BEAN_ID)
	private PbcnnCoreJdbcDao jdbcDao;

	@Resource(name = WorkDocumentPR.BEAN_ID)
	private WorkDocumentPR workDocumentPR;

	@DataProvider
	public List<OrganInfor> getAllOrgan(Map<String, String> parameter) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		Dept dept = (Dept) user.getDepts().get(0);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("deptId", dept.getCDept().getId());
		if (parameter == null || StringUtils.isEmpty(parameter.get("filterValue"))) {
			return this.query("select o from OrganInfor o where o.deptId=:deptId and invalid=false", map);
		} else {
			String filterValue = parameter.get("filterValue").replace(' ', '%');
			map.put("filterValue", "%" + filterValue + "%");
			return this.query("select o from OrganInfor o where o.deptId=:deptId and invalid=false and o.organName like :filterValue", map);
		}
	}

	@DataProvider
	public void loadAllOrganDocuments(Page<OrganDocumentEntity> page, Criteria criteria) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		Dept dept = (Dept) user.getDepts().get(0);
		List<String> childrenIds = this.workDocumentPR.getAllChildOrgDeptId(dept.getCDept().getParentId());
		// System.out.println(dept.getCDept().getName());
		childrenIds.add(dept.getCDept().getId());
		DetachedCriteria detachedCriteria = this.buildDetachedCriteria(criteria, OrganDocumentEntity.class);
		detachedCriteria.add(Restrictions.or(Restrictions.eq("createUser", user.getUsername()), Restrictions.and(Restrictions.in("deptId", childrenIds), Restrictions.eq("state", 20))));
		detachedCriteria.add(Restrictions.eq("invalid", false));
		if (criteria != null && criteria.getOrders() != null && !criteria.getOrders().isEmpty()) {
			com.bstek.dorado.data.provider.Order order = criteria.getOrders().get(0);
			if (order.isDesc()) {
				detachedCriteria.addOrder(Order.desc(order.getProperty()));
			} else {
				detachedCriteria.addOrder(Order.asc(order.getProperty()));
			}
		} else {
			detachedCriteria.addOrder(Order.desc("createDate"));
		}
		this.pagingQuery(page, detachedCriteria);		
	}
	
	@DataProvider
	public List<Record> getUnreport(Map<String, Object> param)throws Exception{
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		if (param == null || param.get("syear")==null || param.get("eyear")==null || param.get("documentType")==null) {
			return new ArrayList<Record>();
		}		
		final Dept dept = (Dept) user.getDepts().get(0);
		final int syear=(int) param.get("syear");
		final int eyear=(int) param.get("eyear");
		final String documentType=(String) param.get("documentType");
		return this.doInHibernateSession(new ISessionCallback<List<Record>>() {

			@Override
			public List<Record> doInSession(Session session) {
				// TODO Auto-generated method stub
				String datasql=" select new map(concat(:years) as years,concat(:documentType) as documentType,o.organName as organName,o.organNum as organCode) from OrganInfor o "
						      +" where o.deptId=:deptId and o.invalid=false and o.id not in (select od.organId from OrganDocumentEntity od where od.deptId=:deptId and od.invalid=false "
						      +" and year(reportDate)>=:syear and year(reportDate)<=:eyear and od.documentType=:documentType and od.state=20) ";
				Query query= session.createQuery(datasql);
				query.setString("years", syear+"年-"+eyear+"年");
				query.setString("documentType", documentType);
				query.setString("deptId", dept.getCDept().getId());
				query.setInteger("syear", syear);
				query.setInteger("eyear", eyear);
				return query.list();
			}
		});
	}
	
	@DataProvider
	public List<OrganDocumentEntity> getUntimelyReport(Map<String, Object> param)throws Exception{
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");		
		if (param == null || param.get("syear")==null || param.get("eyear")==null || param.get("documentType")==null) {
			return new ArrayList<OrganDocumentEntity>();
		}		
		final Dept dept = (Dept) user.getDepts().get(0);
		final int syear=(int) param.get("syear");
		final int eyear=(int) param.get("eyear");
		final String documentType=(String) param.get("documentType");
		final String years=syear+"年-"+eyear+"年";
		return this.doInHibernateSession(new ISessionCallback<List<OrganDocumentEntity>>() {

			@Override
			public List<OrganDocumentEntity> doInSession(Session session){
				// TODO Auto-generated method stub
				String datasql=" select od from OrganDocumentEntity od where od.deptId=:deptId and od.invalid=false and od.reportDate>od.dueDate and od.state=20  "
							  +" and od.documentType=:documentType and year(reportDate)>=:syear and year(reportDate)<=:eyear ";
				Query query= session.createQuery(datasql);
				query.setString("documentType", documentType);
				query.setString("deptId", dept.getCDept().getId());
				query.setInteger("syear", syear);
				query.setInteger("eyear", eyear);
				List<OrganDocumentEntity> rs=query.list();
				List<OrganDocumentEntity> records =new ArrayList<OrganDocumentEntity>();
				for (OrganDocumentEntity organDocumentEntity : rs) {
						try {
							OrganDocumentEntity record=EntityUtils.toEntity(organDocumentEntity);
							EntityUtils.setValue(record, "years", years);
							records.add(record);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					
				}
				return records;
			}
		});
	}

	@DataProvider
	public List<OrganDocumentEntity> getReport(Map<String, Object> param) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		final Dept dept = (Dept) user.getDepts().get(0);

		if (param == null || param.get("syear") == null || param.get("eyear") == null || param.get("isAllOrgan") == null) {
			return new ArrayList<OrganDocumentEntity>();
		}
		final int syear = (int) param.get("syear");
		final int eyear = (int) param.get("eyear");
		final boolean isAllOrgan = (boolean) param.get("isAllOrgan");
		if (!isAllOrgan && param.get("organId") == null) {
			return new ArrayList<OrganDocumentEntity>();
		}
		final String organId = (String) param.get("organId");
		final String years = syear + "年-" + eyear + "年";
		return this.doInHibernateSession(new ISessionCallback<List<OrganDocumentEntity>>() {

			@Override
			public List<OrganDocumentEntity> doInSession(Session session) {
				// TODO Auto-generated method stub
				String datasql = "";
				if (isAllOrgan) {
					datasql = " select od from OrganDocumentEntity od where od.deptId=:deptId and od.invalid=false and od.state=20 and year(reportDate)>=:syear and year(reportDate)<=:eyear ";
				} else {
					datasql = " select od from OrganDocumentEntity od where od.deptId=:deptId and od.invalid=false and od.organId=:organId and od.state=20  " 
				            + " and year(reportDate)>=:syear and year(reportDate)<=:eyear ";
				}
				Query query = session.createQuery(datasql);
				query.setString("deptId", dept.getCDept().getId());
				query.setInteger("syear", syear);
				query.setInteger("eyear", eyear);
				if (!isAllOrgan) {
					query.setString("organId", organId);
				}
				List<OrganDocumentEntity> rs = query.list();
				List<OrganDocumentEntity> records = new ArrayList<OrganDocumentEntity>();
				for (OrganDocumentEntity organDocumentEntity : rs) {
					try {
						OrganDocumentEntity record = EntityUtils.toEntity(organDocumentEntity);
						EntityUtils.setValue(record, "years", years);
						long day = 24 * 60 * 60 * 1000;
						long delta = (organDocumentEntity.getReportDate().getTime() - organDocumentEntity.getReleaseDate().getTime()) / day;
						EntityUtils.setValue(record, "delta", delta);
						records.add(record);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

				}
				return records;
			}
		});
	}

	@DataResolver
	@Transactional
	public void saveOrganDocument(List<OrganDocumentEntity> organDocumentEntities) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null)
			throw new NoneLoginException("请先登录！");
		if (user.getDepts() == null || user.getDepts().isEmpty())
			throw new NoneLoginException("您未设置部门！");
		Dept dept = (Dept) user.getDepts().get(0);
		for (OrganDocumentEntity organDocument : organDocumentEntities) {
			EntityState state = EntityUtils.getState(organDocument);
			OrganDocumentEntity organDocumentEntity = EntityUtils.toEntity(organDocument);
			organDocument.setState(10);
			if (state.equals(EntityState.NEW)) {
				organDocument.setDeptId(dept.getCDept().getId());
				organDocument.setDeptName(dept.getCDept().getName());
				this.save(organDocument);
			} else if (state.equals(EntityState.MODIFIED)) {
				this.update(organDocument);
			} else if (state.equals(EntityState.DELETED)) {
				this.delete(organDocument);
			}

			List<AttachmentEntity> attachments = EntityUtils.getValue(organDocumentEntity, "attachments");
			if (attachments != null) {
				this.update(organDocument);
				for (AttachmentEntity attachmentEntity : attachments) {
					this.workDocumentPR.saveEntity(attachmentEntity);
				}
			}			
		}
	}

	@Expose
	@DataResolver
	@Transactional
	public void submitOrganDocument(OrganDocumentEntity organDocument) throws Exception {
		if (organDocument.getState() != 20) {
			organDocument.setState(20);
			organDocument.setSubmitDate(new Date());
			this.update(organDocument);
		}
	}
}
